var db = module.exports = {
	query: query,
	queryWithParam: queryWithParam,
	queryWithParamSingle: queryWithParamSingle,
	changeDatabase: changeDatabase,
	queryInDatabase: queryInDatabase,
	queryWithParamInDatabase: queryWithParamInDatabase,
	multiStatQueries: multiStatQueries
};

var mysqlConf = require('../../../etc/conf').mysql;
var genericPool = require('generic-pool');

var pool = db.pool = genericPool.Pool({
	name: 'mysql-pool',
	max: 10,
	create: function (cb) {
		try {
			var connection = require('mysql').createConnection({
				'host': mysqlConf.HOST,
				'port': mysqlConf.PORT,
				'user': mysqlConf.USER,
				'password': mysqlConf.PASSWORD,
				'database': mysqlConf.DATABASE,
				'multipleStatements': true
			});

			connection.connect();

			cb && cb(null, connection);
		} catch (e) {
			cb && cb(e);
		}
	},
	destroy: function (conn) {
		try {
			conn.end();
		} catch (e) {
			console.err('Close connection failed.');
		}
	},
	idleTimeoutMillis: 30000,
	priorityRange: 3
});

// cb err, results, fields
function query(sql, cb) {
	pool.acquire(function (err, conn) {
		if (err) {
			return cb && cb(err);
		}

		conn.query(sql, cb);
		pool.release(conn);
	});
}

// cb err, results, fields
function queryWithParam(sql, params, cb) {
	//console.log("sql:" + sql + "  __params:" + params);
	pool.acquire(function (err, conn) {
		if (err) {
			console.log("sql pool.acquire error:" + err.toString() + " obj:" + err);
			return cb && cb(err);
		}

		conn.query(sql, params, function (err, data) {
			if (err) {
				console.log("sql conn.query error:" + err.toString() + " obj:" + err);
				return cb(err, data);
			}
			if (data.length)
				data.forEach(function (each, index) {
					for (var name in each) {
						var lower = name.toLowerCase();
						if (lower != name) {
							each[lower] = each[name];
							delete each[name];
						}
					}
				});
			cb(err, data);
		});
		pool.release(conn);

	});
}
function queryWithParamSingle(sql, params, cb) {
	queryWithParam(sql, params, function (err, data) {
		cb && cb(err, data && data[0]);
	});
}

function changeDatabase(dbName, cb) {
	query('use ' + dbName, cb);
}

function queryInDatabase(dbName, sql, cb) {
	query('use ' + dbName + ';' + sql, function (e, r, f) {
		cb && cb(e, r && r[1], f);
	});
}

function queryWithParamInDatabase(dbName, sql, params, cb) {
	queryWithParam('use ' + dbName + ';' + sql, params, function (e, r, f) {
		cb && cb(e, r && r[1], f);
	});
}

// 同时执行多条sql，没有测试
function multiStatQueries(sql, cb) {
	pool.acquire(function (err, conn) {
		if (err) {
			return cb && cb(err);
		}

		var q = conn.query(sql, cb);
		q
			.on('error', function (err) {
				cb && cb(err);
			})
			.on('fields', function (fields) {
				cb && cb(null, [], f);
			})
			.on('result', function (row) {
				cb && cb(null, r, []);
			})
			.on('end', function () {
				pool.release(conn);
			});
	});
}
